﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.Windows.Threading;
using GalaSoft.MvvmLight.Threading;
using System.ComponentModel;
using GalaSoft.MvvmLight.Messaging;

namespace YouTube.HelperClass
{
    
    /// <summary>
    /// Collection that supports INotifyCollectionChanged notification from seperate threads
    /// </summary>
    /// <typeparam name="T">The type of object to store in the collections</typeparam>
    public class ThreadableObservableCollection<T> : ObservableCollection<T>
    {
        private Dispatcher currentDispatcher;

        /// <summary>
        /// Gets the current dispatcher object
        /// </summary>
        public Dispatcher CurrentDispatcher
        {
            get { return currentDispatcher; }
        }

        /// <summary>
        /// default constructor
        /// Here we must get the Dispatcher object
        /// </summary>
        public ThreadableObservableCollection()
        {
            currentDispatcher = DispatcherHelper.GetCurrentDispatcher();
        }

        /// <summary>
        /// Constructor that gets the dispatcher from outside
        /// </summary>
        /// <param name="dispatcher">The dispatcher to set</param>
        public ThreadableObservableCollection(Dispatcher dispatcher)
        {
            if (dispatcher == null)
                throw new ArgumentNullException("dispatcher", "dispatcher cannot be set to null");
            currentDispatcher = dispatcher;
        }
        public void listShow()
        {
            currentDispatcher.BeginInvoke(new Action(show));
        }
        public void show()
        {
            Messenger.Default.Send<int>(0, "ListBoxShow");
        }

        //public void Add_1(int i, T item)
        //{
        //    SetItem(i, item);
        //}

        //public void loadValues(ObservableCollection<Airports> obj)
        //{
        //     currentDispatcher.BeginInvoke(new Action<ObservableCollection<Airports>>(load), obj);
        //}
        //public void load(ObservableCollection<Airports> obj)
        //{
        //    Airports[] tmp = new Airports[0];
        //    obj.CopyTo(tmp, 0); 
        //    for(int i = obj.Count; i >= 0; i--)
        //        base.Add((Airports)tmp[i]);
        //}

        protected override void InsertItem(int index, T item)
        {
            try
            {
                if (currentDispatcher.CheckAccess())
                    base.InsertItem(index, item);
                else
                    currentDispatcher.BeginInvoke(new Action<int, T>(InsertItem), index, item);
            }
            catch (Exception exe)
            {
            }
        }

        protected override void ClearItems()
        {
            if (currentDispatcher.CheckAccess())
                base.ClearItems();
            else
                currentDispatcher.BeginInvoke(new Action(ClearItems));
        }

        protected override void RemoveItem(int index)
        {
            if (currentDispatcher.CheckAccess())
                base.RemoveItem(index);
            else
                currentDispatcher.BeginInvoke(new Action<int>(RemoveItem), index);
        }

        protected override void SetItem(int index, T item)
        {
            if (currentDispatcher.CheckAccess())
                base.SetItem(index, item);
            else
                currentDispatcher.BeginInvoke(new Action<int, T>(SetItem), index, item);
        }

        protected override void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (currentDispatcher.CheckAccess())
                base.OnPropertyChanged(e);
            else
                currentDispatcher.BeginInvoke(new Action<PropertyChangedEventArgs>(OnPropertyChanged), e);
        }
    }
    public static class DispatcherHelper
    {
        public static Dispatcher GetCurrentDispatcher()
        {
            if (Application.Current != null &&
                                    Application.Current.RootVisual != null &&
                                    Application.Current.RootVisual.Dispatcher != null)
            {
                return Application.Current.RootVisual.Dispatcher;
            }
            else // if we did not get the Dispatcher throw an exception
            {
                throw new InvalidOperationException("This object must be initialized after that the RootVisual has been loaded");
            }
        }
    }
}
